package com.spzx.cart.service.impl;

import com.spzx.cart.api.domain.CartInfo;
import com.spzx.cart.service.ICartService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.common.security.utils.SecurityUtils;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductSkuVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartServiceImpl implements ICartService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RemoteProductService remoteProductService;

    private String getCartKey(Long userId) {
        //定义key user:userId:cart
        return "user:cart:" + userId;
    }

    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        // 首先判断用户登录状态
        Long userId = SecurityUtils.getUserId();
        // 从redis中获取用户购物车数据，若存在，则更新数量，不存在则新增
        String cartKey = getCartKey(userId);
        String hashKey = skuId.toString();
        // 定义商品数量上限
        Integer threshold = 99;
        // redis中采用hash存储 key:cartKey field:skuId value:CartInfo
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        if (hashOps.hasKey(hashKey)) {
            CartInfo cartInfo = hashOps.get(hashKey);
            int totalCount = cartInfo.getSkuNum() + skuNum;
            if (totalCount > threshold)
                throw new ServiceException("商品数量不能超过" + threshold);
            cartInfo.setSkuNum(totalCount);
            hashOps.put(hashKey, cartInfo);
        } else {
            // 若不存在，则远程调用product服务获取商品sku信息，保存到redis中
            // 首先判断购物车中的商品sku种类不能超过50种
            Long count = hashOps.size();
            if (++count > 50) {
                throw new ServiceException("购物车中商品种类不能超过50种");
            }
            // 新建一个CartInfo对象，并远程调用product服务获取商品sku信息
            CartInfo cartInfo = new CartInfo();
            cartInfo.setSkuId(skuId);
            cartInfo.setSkuNum(skuNum);
            R<ProductSkuVo> productSkuResult = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            if (R.FAIL == productSkuResult.getCode())
                throw new ServiceException(productSkuResult.getMsg());
            ProductSkuVo productSkuVo = productSkuResult.getData();
            cartInfo.setSkuId(skuId);
            cartInfo.setSkuName(productSkuVo.getSkuName());
            cartInfo.setThumbImg(productSkuVo.getThumbImg());
            cartInfo.setCartPrice(productSkuVo.getSalePrice());
            cartInfo.setSkuPrice(productSkuVo.getSalePrice());
            cartInfo.setCreateTime(new Date());
            // 保存到redis中
            hashOps.put(hashKey, cartInfo);
        }
    }

    @Override
    public List<CartInfo> getCartList() {
        // 获取用户id
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        // 按商品创建时间排序 新增的商品排在前面
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            cartInfoList.sort((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()));
            return cartInfoList;
        }
        return new ArrayList<>();
    }

    @Override
    public void deleteCart(Long skuId) {
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);
        redisTemplate.opsForHash().delete(cartKey, skuId.toString());
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        // 先获取用户选择的商品
        if (Boolean.TRUE.equals(hashOps.hasKey(skuId.toString()))) {
            CartInfo cartInfoUpd = hashOps.get(skuId.toString());
            // cartInfoUpd 写回缓存
            cartInfoUpd.setIsChecked(isChecked);
            // 更新缓存
            hashOps.put(skuId.toString(), cartInfoUpd);
        }
    }

    @Override
    public void allCheckCart(Integer isChecked) {
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        hashOps.values().forEach(item -> {
            item.setIsChecked(isChecked); // 修改选中状态
            hashOps.put(item.getSkuId().toString(), item); // 更新缓存
        });
    }

    @Override
    public void clearCart() {
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);
        redisTemplate.delete(cartKey);
    }

    /**
     * 查询用户购物车列表中选中商品列表
     *
     * @return 购物车isChecked = 1 的商品列表
     */
    @Override
    public List<CartInfo> getCartCheckedList() {
        //获取购物车key
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);

        HashOperations<String, String, CartInfo> hashOps = redisTemplate.opsForHash();
        List<CartInfo> carInfoList = hashOps.values(cartKey);
        if (!CollectionUtils.isEmpty(carInfoList)) {
            carInfoList = carInfoList
                    .stream()
                    .filter(cartInfo -> cartInfo.getIsChecked() == 1)
                    .collect(Collectors.toList());
        }
        return carInfoList;
    }

    /**
     * 更新购物车商品价格
     *
     * @param userId 用户id
     * @return 更新成功返回true
     */
    @Override
    public Boolean updateCartPrice(Long userId) {
        String cartKey = getCartKey(userId);
        HashOperations<String, String, CartInfo> hashOps = redisTemplate.opsForHash();
        List<CartInfo> cartInfoList = hashOps.values(cartKey);
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            cartInfoList.forEach(cartInfo -> {
                R<ProductSkuVo> productSkuResult = remoteProductService.getSkuPrice(cartInfo.getSkuId(), SecurityConstants.INNER);
                if (R.FAIL == productSkuResult.getCode())
                    throw new ServiceException(productSkuResult.getMsg());
                // 更新购物车商品价格
//                cartInfo.setCartPrice(productSkuResult.getData().getSalePrice());
                cartInfo.setSkuPrice(productSkuResult.getData().getSalePrice());
                hashOps.put(cartKey, cartInfo.getSkuId().toString(), cartInfo);
            });
        }
        return true;
    }

    /**
     * 删除购物车选中商品
     *
     * @param userId 用户id
     * @return
     */
    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            cartInfoList.forEach(cartInfo -> {
                if (cartInfo.getIsChecked() == 1) {
                    hashOps.delete(cartInfo.getSkuId().toString());
                }
            });
        }
        return true;
    }
}
